根據上一篇談到的資料取得策略, 我是選擇了在一開始發送大量請求並存在自己的資料庫, 那麼我接下來要做的事:
首先我先取得所有寶可夢的名稱、照片、招式。
這裡我是先去看了所有寶可夢總共有幾隻,用for 迴圈去對這個數量做一個一個的請求發送。
這裡我故意留了幾個dd(), 說明我在大量發送前先做了屬性是否取得的確認。
解析數據
然後其實我覺得這裡數據的解析其實就是去看對方的API回傳的資料結構, 然後去拿到你想要的資料。比如這裡招式的部分, 我要這隻寶可夢可以學的所有招式的名稱, 但API返回的是招式的名稱還有威力等等…, 我就要去針對名稱的部分做拿取, 並存到陣列
$batchSize = 1; // 可以根據需要調整
$totalPokemons = 1011; // 根據你的實際數量調整
for ($i = 1; $i < $totalPokemons; $i += $batchSize) {
// 取得名稱、照片、招式
$response1 = Http::get("https://pokeapi.co/api/v2/pokemon/$i");
$pokemonDetail = $response1->json();
$name = $pokemonDetail['name'];
// dd($name);
$photo = $pokemonDetail["sprites"]['front_default'];
$moves = $pokemonDetail['moves'];
$moveNames = [];
// 取出此寶可夢所能學的所有的招式名稱
foreach ($moves as $moves) {
$moveNames[] = $moves['move']['name'];
// dd($moveNames);
}
以下的不是針對進化等級的取的, 這裡其實不是我想多打一次API, 而是我想要的某些資料對方就是分成不同的API, 比如下面的進化等級。
他返回的資料結構是比較複雜, 他是一個三維的結構, 我額外寫了一個函數去拿到資料,
// 取得進化等級,這在pokemon-species的進化鏈裡面
$pokemonData = Http::get("https://pokeapi.co/api/v2/pokemon-species/$i")->json();
$getEvolutionChain = $pokemonData["evolution_chain"]['url'];
$evolutionChain = Http::get($getEvolutionChain)->json();
$minLevel = $this->getEvolutionMinLevel($evolutionChain, $name);
// dd($minLevel);
最後儲存的部分我主要都是存在Race表單, 但關於技能的部分, 我其實有一張Race表單,
他是和技能表單多對多關聯,所以我是將技能存到這裡。
$race = Race::create([
'name' => $name,
'photo' => $photo,
'evolution_level' => $minLevel
]);
foreach ($moveNames as $moveName) {
// 先找出或創建招式
$move = Skill::firstOrCreate(['name' => $moveName]);
// 關聯到寶可夢
$race->skills()->attach($move->id);
}
最小進化等級解析:
當你打上https://pokeapi.co/api/v2/evolution-chain/1/ 這隻api,他會出現以下結果:
{
"baby_trigger_item": null,
"chain": {
"evolution_details": [],
"evolves_to": [
{
"evolution_details": [
{
"gender": null,
"held_item": null,
"item": null,
"known_move": null,
"known_move_type": null,
"location": null,
"min_affection": null,
"min_beauty": null,
"min_happiness": null,
"min_level": 16,
"needs_overworld_rain": false,
"party_species": null,
"party_type": null,
"relative_physical_stats": null,
"time_of_day": "",
"trade_species": null,
"trigger": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/evolution-trigger/1/"
},
"turn_upside_down": false
}
],
"evolves_to": [
{
"evolution_details": [
{
"gender": null,
"held_item": null,
"item": null,
"known_move": null,
"known_move_type": null,
"location": null,
"min_affection": null,
"min_beauty": null,
"min_happiness": null,
"min_level": 32,
"needs_overworld_rain": false,
"party_species": null,
"party_type": null,
"relative_physical_stats": null,
"time_of_day": "",
"trade_species": null,
"trigger": {
"name": "level-up",
"url": "https://pokeapi.co/api/v2/evolution-trigger/1/"
},
"turn_upside_down": false
}
],
"evolves_to": [],
"is_baby": false,
"species": {
"name": "venusaur",
"url": "https://pokeapi.co/api/v2/pokemon-species/3/"
}
}
],
"is_baby": false,
"species": {
"name": "ivysaur",
"url": "https://pokeapi.co/api/v2/pokemon-species/2/"
}
}
],
"is_baby": false,
"species": {
"name": "bulbasaur",
"url": "https://pokeapi.co/api/v2/pokemon-species/1/"
}
},
"id": 1
}
也就是他每一個進化鏈其實是包含從最初還未進化的寶可夢一直到進化的最終形態,會一直都包含在同一個進化鏈裡面。
解析過程
public function getEvolutionMinLevel($chain, $pokemonName)
{
// 如果是第一階段的寶可夢
if ($chain['chain']['species']['name'] == $pokemonName) {
// 查看它的進化細節,找到進化等級
if (isset($chain['chain']['evolves_to'][0]['evolution_details'][0]['min_level'])) {
return $chain['chain']['evolves_to'][0]['evolution_details'][0]['min_level'];
}
// 代表他不用進化
return null;
}
return $this->searchEvolutionLevel($chain['chain'], $pokemonName);
}
public function searchEvolutionLevel($chain, $pokemonName)
{
if ($chain['species']['name'] == $pokemonName) {
if (isset($chain['evolves_to'][0]['evolution_details'][0]['min_level'])) {
return $chain['evolves_to'][0]['evolution_details'][0]['min_level'];
}
// 可能代表此為最高級
return null;
}
// 重複以上過程直到找到該寶可夢
foreach ($chain['evolves_to'] as $nextChain) {
$level = $this->searchEvolutionLevel($nextChain, $pokemonName);
if ($level !== null) {
return $level;
}
}
return null;
}
雖然資料是取得了但其實還有一些問題:
因為我是透過在一開始去第三方取得所有資料的方式,所以我必須考慮到,跟第三方的同步問題,這個部分的設定我會在下一章分享。
想當然爾, 我剛剛那種發送方式, 一個循環會發送3次api, 而我有幾隻寶可夢就是乘以3, 所以總共是3000多次, 然後再加上我每次存入資料庫的時間, 我每做一次這樣的資料的取得, 差不多會花個30~40 分鐘。
對於如何改善,後續有時間我再來研究。